{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.6. Using stride tricks with NumPy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def aid(x):\n",
    "    # This function returns the memory\n",
    "    # block address of an array.\n",
    "    return x.__array_interface__['data'][0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(8,)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.zeros(10)\n",
    "x.strides"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(80, 8)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = np.zeros((10, 10))\n",
    "y.strides"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 1000\n",
    "a = np.arange(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.lib.stride_tricks.as_strided(a, (n, n), (0, 8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  0,   1,   2, ..., 997, 998, 999],\n",
       "       [  0,   1,   2, ..., 997, 998, 999],\n",
       "       [  0,   1,   2, ..., 997, 998, 999],\n",
       "       ...,\n",
       "       [  0,   1,   2, ..., 997, 998, 999],\n",
       "       [  0,   1,   2, ..., 997, 998, 999],\n",
       "       [  0,   1,   2, ..., 997, 998, 999]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1000000, (1000, 1000), 8000000)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.size, b.shape, b.nbytes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "766 µs ± 2.59 µs per loop (mean ± std. dev. of 7 runs,\n",
      "1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit b * b.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5.55 ms ± 9.1 µs per loop (mean ± std. dev. of 7 runs,\n",
      "100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "np.tile(a, (n, 1)) * np.tile(a[:, np.newaxis], (1, n))"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
